package com.amat0urheu.controller.studentController;

import ch.qos.logback.core.net.SyslogOutputStream;
import com.alibaba.fastjson.JSONObject;
import com.amat0urheu.config.Constant;
import com.amat0urheu.config.security.MyUserDetails;
import com.amat0urheu.dao.*;
import com.amat0urheu.pojo.OperationLog;
import com.amat0urheu.pojo.ReturnRes;
import com.amat0urheu.pojo.User;
import com.amat0urheu.service.LogService;
import com.amat0urheu.service.TeamService;
import com.amat0urheu.service.UserChaMapService;
import com.amat0urheu.service.UserService;
import com.amat0urheu.service.impl.LoginServiceImpl;
import com.amat0urheu.util.generator.ShortUUID;
import com.github.pagehelper.PageInfo;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/api")
public class UserController {

    final UserService userService;
    final UserChaMapService userChaMapService;
    final UserMapper userMapper;
    final ChaCommentMapper chaCommentMapper;
    final WpCommentMapper wpCommentMapper;
    final LearnCommentMapper learnCommentMapper;
    final LoginServiceImpl loginService;
    final Pattern usernamePat = Pattern.compile("^(?!_)(?!.*?_$)[a-zA-Z0-9_\\u4e00-\\u9fa5]+$");
    final Pattern passwordPat = Pattern.compile("^.{6,20}$");
    final TeamService teamService;

    @Autowired
    LogService logService;
    @Autowired
    public UserController(UserService userService, UserChaMapService userChaMapService, UserMapper userMapper, ChaCommentMapper chaCommentMapper, WpCommentMapper wpCommentMapper, LearnCommentMapper learnCommentMapper, LoginServiceImpl loginService,TeamService teamService) {

        this.userService = userService;
        this.userChaMapService = userChaMapService;
        this.userMapper = userMapper;
        this.chaCommentMapper = chaCommentMapper;
        this.wpCommentMapper = wpCommentMapper;
        this.learnCommentMapper = learnCommentMapper;
        this.loginService = loginService;
        this.teamService = teamService;
    }

    @GetMapping("/userInfo/{id:\\d+}")  // 废弃
    public ReturnRes queryOneById(@PathVariable int id) {
        User user = userMapper.selectUserByIdForUser(id);
        if (user != null) {
            briefUserView(user);
            user.setRankTitle();
            return new ReturnRes(true, user);
        } else {
            return new ReturnRes(false, "id not found");
        }
    }

    @GetMapping("/user")
    public ReturnRes query(@RequestParam(required = false) String name) {
        if (name != null) {
            return queryOneByName(name);
        }
        List<User> userList = userMapper.selectAllUser();
        if (userList != null) {
            return new ReturnRes(true, userList);
        } else {
            return new ReturnRes(false);
        }
    }

    @GetMapping("/user/{id:\\d+}")
    public ReturnRes queryOneByIdForUser(@PathVariable int id) {
        User user = userMapper.selectUserByIdForUser(id);
        if (user != null) {
            user.setRankTitle();
            return new ReturnRes(true, user);
        } else {
            return new ReturnRes(false, "id not found");
        }
    }

    @GetMapping("/user/{pageSize:\\d+}/{pageNum:\\d+}")
    @PreAuthorize("hasAuthority('ROLE_admin')")
    public ReturnRes queryByPage(@PathVariable int pageSize,
                                 @PathVariable int pageNum) {
        PageInfo<User> pageInfo = userService.getAllUserByPage(pageNum, pageSize);
        if (pageInfo != null) {
            return new ReturnRes(true, pageInfo);
        }
        return new ReturnRes(false);
    }

    public ReturnRes queryOneByName(@RequestParam String name) {
        User user = userService.getByUserName(name);
        if (user != null) {
//            briefUserView(user);
            return new ReturnRes(true, user);
        } else {
            return new ReturnRes(false, "name not found");
        }
    }


    @PostMapping("/user/updatePassword")
    public ReturnRes updateUserPassword(@RequestParam(name = "oldPassword") String oldPassword,
                                        @RequestParam(name = "newPassword") String newPassword,
                                        Authentication authentication) {


        return userService.updatePassWord(oldPassword,newPassword,authentication.getName());

    }


    /**
     *
     * @param action 对用户的操作名称
     * @param userJson
     * @param authentication 用于鉴权
     * @param response
     * @return
     */

    @PostMapping("/user")
    public ReturnRes operate(@RequestParam String action,
                             @RequestParam(name = "data") String userJson,
                             Authentication authentication,
                             HttpServletResponse response) {
        SecurityExpressionRoot securityExpressionRoot = new SecurityExpressionRoot(authentication) {};
        User user = JSONObject.parseObject(userJson, User.class);

        if (action.equals("save")) {
            OperationLog operationLog = new OperationLog();
            operationLog.setOperateTime(new Date());
            operationLog.setUsername("管理员");
            operationLog.setAction("创建用户: "+user.getUname());
            logService.inserSysLog(operationLog);
            if (!securityExpressionRoot.hasRole("admin")) {
                response.setStatus(403);
                return new ReturnRes(false, "Permission is not allowed.");
            }

            return save(user);
        } if (action.equals("remove")) {

            if (!securityExpressionRoot.hasRole("admin")) {
                response.setStatus(403);
                return new ReturnRes(false, "Permission is not allowed.");
            }
            OperationLog operationLog = new OperationLog();
            operationLog.setOperateTime(new Date());
            operationLog.setUsername("管理员");
            operationLog.setAction(user.getUname()+"删除用户");

            logService.inserSysLog(operationLog);
            return remove(user);
        } if (action.equals("update")) {
        /*    if (!securityExpressionRoot.hasRole("admin")) {
               *//* System.err.println(user+"  "+authentication.getName());
                if (!checkPermission(user, authentication.getName())) {
                    response.setStatus(403);
                    return new ReturnRes(false, "Permission is not allowed.");
                }
                filterDangerOperation(user); // 普通用户操作限制*//*
            }*/
            OperationLog operationLog = new OperationLog();
            operationLog.setOperateTime(new Date());
            operationLog.setUsername(user.getUname());
            operationLog.setAction("更新数据");

            logService.inserSysLog(operationLog);
            return update(user);
        } else {
            return new ReturnRes(false, "action value error");
        }
    }

    @RequestMapping("/user/getMe")
    public ReturnRes getMe(Authentication authentication) {

        Integer uid = ((MyUserDetails)authentication.getPrincipal()).getUid();
        User user = userMapper.selectUserByIdForUser(uid);
        if (user != null) {
            user.setRankTitle();
            return new ReturnRes(true, user);
        } else {
            return new ReturnRes(false, "error, please repeat");
        }
    }
@Autowired
TeamMapper teamMapper;
    @PostMapping("/admin/userAddSome")
    public ReturnRes addSome(@RequestParam(name = "file") MultipartFile file) throws Exception {

        if (file.isEmpty()) {
            return new ReturnRes(false, "请选择一个Excel文件进行上传。");
        }
        if (!file.getOriginalFilename().endsWith(".xls") && !file.getOriginalFilename().endsWith(".xlsx")) {
            return new ReturnRes(false, "请选择一个Excel文件进行上传。"); // Return an error response for a non-Excel file
        }

        Workbook workbook = new HSSFWorkbook(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0); // 假设文件的第一个Sheet包含用户信息
        Iterator<Row> rowIterator = sheet.iterator();
        User user =new User();
        int i=0;
        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();
            if (row.getRowNum() == 0) {
                continue; // 跳过标题行
            }
            user.setUname(row.getCell(1)+"");
            user.setUpassword(row.getCell(2)+"");
            user.setTeamName(row.getCell(3)+"");
            String  iscapTain=row.getCell(4)+"";
            if(iscapTain.equals("是")){
                Integer hasTeam=teamMapper.hasTeam(user.getTeamName());
                if(hasTeam!=0){//队伍存在,更新队长
                    teamMapper.updateCaptainofTeam(user.getTeamName(),user.getUname());
                }else {//队伍不存在 并且将其设置队长
                    teamMapper.addTeam(user.getTeamName(),user.getUname());
                }
            }else {
                //不是队长
                Integer hasTeam=teamMapper.hasTeam(user.getTeamName());
                if(hasTeam!=0){//队伍存在
                //啥都不干,
                }else {//队伍不存在 并且将其设置队长
                    teamMapper.addTeam(user.getTeamName(),null);
                }
            }
            user.setScore(0);
            user.setRole("ROLE_user");
             save(user);

        }
return new ReturnRes(true,"创建成功");


    }
    /**
     * 所有人都能用的注册接口
     * @param username
     * @param password
     * @param passwordR
     * @return
     */
    @PostMapping("/register")
    public ReturnRes register(@RequestParam String username,
                              @RequestParam(defaultValue = "") String password,
                              @RequestParam(defaultValue = "") String passwordR,
                              @RequestParam String captchaId,
                              @RequestParam String captcha) {
        if (!loginService.validateCaptcha(username, captcha, captchaId)) {
            return new ReturnRes(false, "验证码输入错误");
        }
        if (!password.equals(passwordR)) {
            return new ReturnRes(false, "两次密码不一致");
        }
        User user = new User(username, password);
        user.setRole(Constant.ROLE_USER);
        user.setSkill("");

        return save(user);

    }

    public ReturnRes save(User user) {

        ReturnRes checkRes = checkUserInfo(user);
        if (checkRes != null) {
            return checkRes;
        }
        if (userService.usernameIsRepeat(user.getUname())) {
            return new ReturnRes(false, "用户名已存在");
        }

        user.setUpassword(new BCryptPasswordEncoder().encode(user.getUpassword()));
        user.setUid(ShortUUID.generateUid());
        user.setRegTime(new Date());
        setAllScoreZero(user);

        try {
            if (userService.save(user)) {
                briefUserView(user);
                return new ReturnRes(true, user);
            } else {
                return new ReturnRes(false);
            }
        } catch (DuplicateKeyException e) {
            e.printStackTrace();
            return new ReturnRes(false, "repeat oper");
        }
    }



    public ReturnRes remove(User user) {
        userChaMapService.removeByUid(user.getUid());   // 先删除用户的做题信息
        teamService.reduceTeamNum(user.getTeamName());
        chaCommentMapper.deleteByUid(user.getUid());    //删除用户的评论信息
        wpCommentMapper.deleteByUid(user.getUid());
        learnCommentMapper.deleteByUid(user.getUid());
        if (userService.removeById(user)) {
            briefUserView(user);
            return new ReturnRes(true, user);
        } else {
            return new ReturnRes(false, "id not found");
        }
    }

    public ReturnRes update(User user) {

        ReturnRes checkRes = checkUserInfo(user);
        if (checkRes != null) {
            return checkRes;
        }

        if (user.getUpassword() != null) {

            user.setUpassword(new BCryptPasswordEncoder().encode(user.getUpassword()));
        }

        try {

            if (userService.updateById(user)) {
                briefUserView(user);
                return new ReturnRes(true, user);
            } else {
                return new ReturnRes(false, "用户id不存在");
            }
        } catch (Exception e) {

            return new ReturnRes(false, "用户名已经存在");
        }
    }

    /**
     * 过滤返回给前端的数据
     * @param user
     */
    public void briefUserView(User user) {
        user.setRegTime(null);
        user.setWeb(null);
        user.setPwn(null);
        user.setRe(null);
        user.setCrypto(null);
        user.setMisc(null);
        user.setOther(null);
        user.setRank(null);
        user.setLevel(null);
        user.setTitle(null);
    }

    public void filterDangerOperation(User user) {
        user.setRole(null);
        user.setRegTime(null);
    }

    /**
     * 将新用户的分数置为0
     * @param user
     */
    public void setAllScoreZero(User user) {
        user.setWeb(0);
        user.setPwn(0);
        user.setRe(0);
        user.setCrypto(0);
        user.setMisc(0);
        user.setOther(0);
        user.setScore(0);
    }

    /**
     * 检查用户与操作对象是否匹配
     * @param operedUser
     * @param username
     * @return
     */
    public boolean checkPermission(User operedUser, String username) {
        int uid = userService.getIdByUserName(username);
        return uid == operedUser.getUid();
    }

    @GetMapping("/user/search/{pageSize:\\d+}/{pageNum:\\d+}")
    public ReturnRes searchUserByPage(@PathVariable int pageSize,
                                      @PathVariable int pageNum,
                                      @RequestParam String key,
                                      @RequestParam String value) {
        return userService.searchUserByPage(key, value, pageNum, pageSize);
    }
    @GetMapping("/user/super/{username}")
    public ReturnRes checkIfSuperUser(Authentication authentication, @PathVariable String username) {
        userService.checkIfSuperUser(authentication.getName());
        return new ReturnRes(true,200);
    }
    public ReturnRes checkUserInfo(User user) {
//        System.err.println(user);
        Matcher m1 = usernamePat.matcher(user.getUname());
        if (!m1.matches()) {
            return new ReturnRes(false, "用户名只含有汉字、数字、字母、下划线不能以下划线开头和结尾");
        }
        if (user.getUpassword() != null) {
            Matcher m2 = passwordPat.matcher(user.getUpassword());
            if (!m2.matches()) {
                return new ReturnRes(false, "密码长度必须为6-20");
            }
        }
          return null;
    }
}
